using System.Diagnostics;
using System.Windows.Forms;

namespace Scenario_Editor.Windows
{
    public partial class LoadingWindow : UserControl
    {
        #region Private Fields

        private ObjectLoadStatus LoadingStatus;
        private Timer timer;

        #endregion Private Fields

        #region Public Constructors

        public LoadingWindow(Form owner)
            : this()
        {
        }

        public LoadingWindow()
        {
            InitializeComponent();
            this.timer = new Timer();
            timer.Interval = 500;
            timer.Tick += timer_Tick;
        }

        #endregion Public Constructors

        #region Private Delegates

        private delegate void HideDelegate();

        private delegate void SetProgressbarDelegate(int numberOfEntries, string text);

        private delegate void SetTextDelegate(string text);

        private delegate void SetValueDelegate(int value);

        private delegate void SetVisibleDelegate(bool visible);

        private delegate void ShowDelegate();

        #endregion Private Delegates

        #region Public Properties

        public new string Text
        {
            get
            {
                return this.label1.Text;
            }
            set
            {
                this.label1.Text = value;
                if (this.Visible)
                {
                    Application.DoEvents();
                    this.Invalidate();
                }
            }
        }

        public int Value
        {
            get
            {
                return this.progressBar1.Value;
            }
            set
            {
                if (this.progressBar1.Maximum >= value)
                {
                    if (this.progressBar1.Value != value)
                    {
                        if (this.progressBar1.InvokeRequired)
                            this.progressBar1.BeginInvoke(new System.Action(() => this.progressBar1.Value = value));
                        else
                            this.progressBar1.Value = value;

                        if (this.Visible)
                        {
                            this.Invalidate();
                            Application.DoEvents();
                        }
                    }
                }
                else
                    Debug.WriteLine("progressbar max value is too small for new value");
            }
        }

        #endregion Public Properties

        #region Public Methods

        public void SetObjectToMonitoring(ObjectLoadStatus LoadingStatus)
        {
            this.LoadingStatus = LoadingStatus;
        }

        public void SetProgressbar(int numberOfEntries, string text)
        {
            if (!this.InvokeRequired)
            {
                this.label1.Text = text;
                this.progressBar1.Minimum = 0;
                this.progressBar1.Maximum = numberOfEntries;
                this.Value = 0;
                if (this.Visible)
                    Application.DoEvents();
            }
            else
            {
                SetProgressbarDelegate showProgressbar = new SetProgressbarDelegate(this.SetProgressbar);
                this.Invoke(showProgressbar, new object[]
                {
                    numberOfEntries, text
                });
            }
        }

        #endregion Public Methods

        #region Internal Methods

        internal void ClearObjectLoadingStatus()
        {
            this.LoadingStatus = null;
        }

        internal void SetText(string text)
        {
            if (!this.InvokeRequired)
            {
                this.Text = text;
            }
            else
            {
                SetTextDelegate setText = new SetTextDelegate(SetText);
                this.Invoke(setText, new object[] { text });
            }
        }

        internal void SetValue(int newValue)
        {
            if (!this.InvokeRequired)
            {
                this.Value = newValue;
            }
            else
            {
                SetValueDelegate setValue = new SetValueDelegate(SetValue);
                this.Invoke(setValue, new object[] { newValue });
            }
        }

        internal void SetVisible(bool visible)
        {
            if (!this.InvokeRequired)
            {
                if (visible)
                {
                    timer.Enabled = true;
                    if (!this.InvokeRequired)
                    {
                        this.Show();
                    }
                    else
                    {
                        ShowDelegate show = new ShowDelegate(Show);
                        this.Invoke(show);
                    }
                }
                else
                {
                    timer.Enabled = false;
                    if (!this.InvokeRequired)
                    {
                        this.Hide();
                    }
                    else
                    {
                        HideDelegate hide = new HideDelegate(Hide);
                        this.Invoke(hide);
                    }
                }
                if (this.Visible)
                    Application.DoEvents();
            }
            else
            {
                SetVisibleDelegate setVisible = new SetVisibleDelegate(SetVisible);
                this.Invoke(setVisible, new object[] { visible });
            }
        }

        #endregion Internal Methods

        #region Private Methods

        private void SetProgressbarInvoke(int numberOfEntries, string text)
        {
        }

        private void timer_Tick(object sender, System.EventArgs e)
        {
            if (this.LoadingStatus != null)
            {
                this.progressBar1.Maximum = this.LoadingStatus.MaxValue;
                SetText(this.LoadingStatus.Text);
                SetValue(this.LoadingStatus.Value);
            }
        }

        #endregion Private Methods

        #region Public Classes

        public class ObjectLoadStatus
        {
            #region Private Fields

            private int maxValue;
            private string text = string.Empty;

            private int value;

            #endregion Private Fields

            #region Public Properties

            public int MaxValue
            {
                get { return maxValue; }
                set { maxValue = value; }
            }

            public string Text
            {
                get
                {
                    string copyOfText;
                    lock (text)
                    {
                        copyOfText = text;
                    }
                    return copyOfText;
                }
                set
                {
                    lock (text)
                        text = value;
                }
            }

            public int Value
            {
                get { return value; }
                set { this.value = value; }
            }

            #endregion Public Properties
        }

        #endregion Public Classes
    }
}